<template>
    <div>
        <el-upload ref="uploadRef" :action="actionUrl" v-model:file-list="imageUrlList" :disabled="disabledValue"
            list-type="picture-card" :headers="headers" :data="payload" :limit="limit" :on-success="handleSuccess"
            :before-upload="handleBeforeUpload" :on-error="handleError">
            <el-icon>
                <ele-Plus />
            </el-icon>
            <template #file="{ file }">
                <div>
                    <img v-if="!ifMP4(file)" class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
                    <video v-if="ifMP4(file)" class="el-upload-list__item-thumbnail" alt="">
                        <source :src="file.url" type="video/mp4" />
                    </video>
                    <span class="el-upload-list__item-actions">
                        <span class="el-upload-list__item-preview" @click="handlePreview(file)">
                            <el-icon><ele-ZoomIn /></el-icon>
                        </span>
                        <span v-if="!disabledValue" class="el-upload-list__item-delete" @click="handleRemove(file)">
                            <el-icon>
                                <ele-Delete />
                            </el-icon>
                        </span>
                    </span>
                </div>
            </template>
        </el-upload>
        <el-dialog v-model="dialogVisible" @on-close="onClosePreview">
            <img w-full :src="preViewUrl" alt="图片预览" />
        </el-dialog>
        <el-dialog v-model="dialogVideoVisible" @onClose="onClosePreview">
            <video ref="videoRef" :controls="true" alt="视频预览">
                <source :src="preViewUrl" type="video/mp4" />
            </video>
        </el-dialog>
    </div>
</template>

<script lang="ts">
import { reactive, toRefs, defineComponent, ref, onMounted } from 'vue';
import { UploadFile, UploadFiles, UploadRawFile } from 'element-plus'
import { ElMessage } from 'element-plus'
import type { FormInstance } from 'element-plus';
import useFileInfo from '/@/api/jdfsystem/file-info';
import { useEmployeeStore } from '/@/stores/employee-info';
import MESSAGE from '/@/enums/message-enum';
import { handleDetail, handleIsMP4, handleBuildUploadInfo } from '../file-info-wrap';

interface State {
    actionUrl: string,
    headers: any,
    multiple: boolean | false,
    name: string,
    payload: any,
    disabledValue: boolean | false,
    accept: string,
    limit: number | 1,
    dialogVisible: boolean | false,
    dialogVideoVisible: boolean | false,
    fileIdList: string[] | [],
    imageUrlList: { name: string, url: string }[] | [],
    mp4Map: Map<string, boolean>,
    preViewUrl: string | undefined,
}

export default defineComponent({
    name: 'avatar',
    props: {
        imageIdList: {
            type: Array<string>,
            default: [],
        },
        multiple: {
            type: Boolean,
            default: false,
        },
        name: {
            type: String,
            default: 'file',
        },
        accept: {
            type: String,
            defalut: 'image/png,image/jpeg,image/jpg',
        },
        limit: {
            type: Number,
            default: 1,
        },
        sizeLimit: {
            type: Number,
            default: 2,
        },
        payload: {
            type: Object,
            default: undefined
        },
        disabled: {
            type: Boolean,
            default: false,
        }
    },
    emits: ['onSuccess',],
    setup(props, context) {
        const fileStore = useFileInfo();
        const employeeStore = useEmployeeStore();
        const { multiple, name, accept, limit, imageIdList, payload, disabled, sizeLimit } = { ...props };
        const state = reactive<State>({
            actionUrl: fileStore.uploadUrl(),
            headers: {
                'Authorization': employeeStore.getToken(),
            },
            multiple: multiple,
            name: name,
            disabledValue: disabled,
            accept: accept || 'image/png,image/jpeg,image/jpg',
            limit: limit,
            fileIdList: [...imageIdList],
            imageUrlList: [],
            mp4Map: new Map(),
            payload: payload,
            dialogVisible: false,
            dialogVideoVisible: false,
            preViewUrl: undefined,
        });
        const methodMap = reactive({
            handleSuccess: async function (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) {
                const res: any = uploadFile.response;
                if (MESSAGE.OK !== res.code) {
                    context.emit('onSuccess', []);
                    ElMessage.error('图片上传失败：' + res.msg);
                    return;
                }
                const fileIdList: string[] = uploadFiles.filter(f => f.status === 'success').map(m => {
                    const response: any = m.response;
                    return response ? response.data : m.name;
                });
                // 缓存视频标识
                methodMap.putMP4(uploadFile, await methodMap.isMP4(uploadFile));
                // 缓存当前文件ID
                state.fileIdList = [...fileIdList];
                context.emit('onSuccess', state.fileIdList);
            },
            handleRemove: function (uploadFile: UploadFile) {
                const response: any = uploadFile.response;
                const fileId = response.data ? response.data : uploadFile.name;
                const fileIdList: string[] = state.fileIdList.filter(f => f !== fileId);
                state.fileIdList = [...fileIdList];
                uploadRef.value.handleRemove(uploadFile);
                context.emit('onSuccess', state.fileIdList);
            },
            handleError: function (error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles) {
                console.info(uploadFile);
                ElMessage.error('图片上传失败：' + error.message);
            },
            handleBeforeUpload: function (rawFile: UploadRawFile) {
                const imageTypeList: string[] = state.accept.split(',');
                if (!imageTypeList.includes(rawFile.type)) {
                    console.info("支持格式:" + state.accept);
                    ElMessage.error('图片必须是' + state.accept + '格式！');
                    return false;
                }
                if (rawFile.size / 1024 / 1024 > sizeLimit) {
                    ElMessage.error('图片大小不能超过：' + sizeLimit + 'MB!')
                    return false
                }
                return true;
            },
            handlePreview: async function (uploadFile: UploadFile) {
                state.preViewUrl = uploadFile.url;
                state.dialogVideoVisible = await this.isMP4(uploadFile);
                state.dialogVisible = !state.dialogVideoVisible;
            },
            isMP4: async function (uploadFile: UploadFile) {
                const response: any = uploadFile.response;
                if (response && response.data) {
                    const fileId: string = response.data;
                    const res = await handleDetail(fileId);
                    const { code, data } = res;
                    if (code === MESSAGE.OK && data && data) {
                        return handleIsMP4(data);
                    }
                }
                return false;
            },
            putMP4: function (uploadFile: UploadFile, flag: boolean) {
                const response: any = uploadFile.response;
                if (response && response.data) {
                    const fileId: string = response.data;
                    state.mp4Map.set(fileId, flag);
                }
            },
            ifMP4: function (uploadFile: UploadFile) {
                const response: any = uploadFile.response;
                if (response && response.data) {
                    const fileId: string = response.data;
                    return state.mp4Map.get(fileId);
                }
                return false;
            },
            clear: function () {
                state.imageUrlList = [];
                state.fileIdList = []
                uploadRef.value.clearFiles(state.fileIdList);
                context.emit('onSuccess', state.fileIdList);
            },
            onClosePreview: function () {
                if (state.dialogVideoVisible) {
                    uploadRef.value.pause();
                }
                state.dialogVideoVisible = false;
                state.dialogVisible = false;
            }
        });
        const formRef = ref<FormInstance>();
        const uploadRef = ref();
        const videoRef = ref();
        onMounted(async () => {
            if (!state.fileIdList || state.fileIdList.length == 0) {
                return;
            }
            const response = await handleDetail(state.fileIdList[0]);
            const { code, data } = response;
            if (code === MESSAGE.OK && data) {
                state.mp4Map.set(data.id as string, handleIsMP4(data));
                state.imageUrlList = [...handleBuildUploadInfo(state.fileIdList)];
            }
        });
        return {
            formRef,
            uploadRef,
            videoRef,
            ...toRefs(state),
            ...toRefs(methodMap),
        };
    },
});
</script>
<style scoped lang="scss">
@import '/@/views/file-info/file-info.scss';
</style>
